use super::EntryInfo;
use crate::file_system::read_general_json;
use serde_json::Value;
use std::path::{Path, PathBuf};

#[derive(Clone, Debug)]
pub struct NpmModuleInfo {
    pub api_json: PathBuf,
    pub package_json: PathBuf,
    pub package_name: String,
}

const ENTRY_NAME: &str = "entryInfo";
const API_JSON: &str = "api.json";
const PACKAGE_JSON: &str = "package.json";
impl NpmModuleInfo {
    // 当前项目安装这个模块
    pub fn new_installed(project_dir: &Path, dependency_name: &str) -> Self {
        let module_path = &get_node_module_path(dependency_name);
        Self {
            api_json: PathBuf::from(project_dir).join(module_path).join(API_JSON),
            package_json: PathBuf::from(project_dir)
                .join(module_path)
                .join(PACKAGE_JSON),
            package_name: dependency_name.to_string(),
        }
    }

    // 当前的项目就是模块自身
    pub fn new_for_dev(project_dir: &Path) -> Self {
        Self {
            api_json: PathBuf::from(project_dir).join(API_JSON),
            package_json: PathBuf::from(project_dir).join(PACKAGE_JSON),
            package_name: ".".to_string(),
        }
    }

    pub fn try_get_entry_info(&self) -> Option<EntryInfo> {
        let package_json = &read_general_json(&self.package_json).ok()?;
        if let Some(name) = try_get_entry_name(package_json) {
            return Some(EntryInfo {
                name,
                package_name: self.package_name.clone(),
            });
        }
        None
    }
}

fn get_node_module_path(lib_name: &str) -> PathBuf {
    let mut paths = PathBuf::from("node_modules");
    paths.push(lib_name);
    paths
}

fn try_get_entry_name(value: &Value) -> Option<String> {
    if let Value::Object(map) = value {
        if let Some(Value::Object(entry_info)) = map.get(ENTRY_NAME) {
            if let Some(Value::String(name)) = entry_info.get("name") {
                return Some(name.to_string());
            }
        }
    }
    None
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_try_get_entry_name() {
        let json = r#"{
  "name": "todolist_list",
  "private": false,
  "version": "0.0.4",
  "type": "module",
  "main": "src/index",
  "scripts": {
  },
  "entryInfo":{
    "name": "TodoList"
  },
  "peerDependencies": {
    "@ant-design/icons-vue": "^7.0.1",
    "ant-design-vue": "^4.2.6",
    "api-factory": "git+https://gitee.com/hanshu_alan/api-factory.git#0.1.0",
    "axios": "^1.7.9",
    "lodash": "^4.17.21",
    "vue": "^3.5.12"
  },
  "devDependencies": {
    "@ant-design/icons-vue": "^7.0.1",
    "ant-design-vue": "^4.2.6",
    "api-factory": "git+https://gitee.com/hanshu_alan/api-factory.git#0.1.0",
    "api-factory-plugin": "git+https://gitee.com/hanshu_alan/api-factory-plugin.git#0.1.3",
    "axios": "^1.7.9",
    "lodash": "^4.17.21",
    "vue": "^3.5.12",
    "@vitejs/plugin-vue": "^5.1.4",
    "chokidar": "^4.0.1",
    "sass": "^1.82.0",
    "typescript": "~5.6.2",
    "unplugin-vue-components": "^0.27.5",
    "vite": "^5.4.10",
    "vue-tsc": "^2.1.8"
  }
}
            "#;
        let json_value = &serde_json::from_str(json).expect("解析json错误");
        assert_eq!(try_get_entry_name(json_value), Some("TodoList".to_string()));
    }
}
